#ifndef DATA_H
#define DATA_H

#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include "../const/const.h"

class Data{
	unsigned int lenth;
	unsigned int cur_column;
	unsigned int column_num;
	unsigned int nullInf;
	std::string data;
	std::vector<std::string> origin_data;
	std::vector<bool> nullList;
	std::vector<unsigned int> max_length;
	std::string RID;
public:
	Data(){
		nullList.clear();
		nullList.push_back(false);
	}
	~Data(){}
public:
	static std::string intZip(unsigned int num, int len){
		std::string r = "";
		for(int i = 0; i < len; ++i){
			r += char(num & 0xFF);
			num = num >> 8;
		}
		return r;
	}
	static int intUnzip(char* buf, int len){
		int res = 0;
		for(int i = len - 1; i >= 0; --i)
			res = (res << 8) + (int)((unsigned char)(*(buf+i)));
		return res;
	}
	static std::string fillStr(std::string str, int strLen){
		if(str.size() > strLen)
			return str.substr(0, strLen);
		for(int i = str.length(); i < strLen; ++i)
			str += char(0);
		return str;
	}
	void readData(char* buf, std::vector<std::string>& data, int& length, int& colNull){
		std::string single_data;
		int column_num = intUnzip(buf+1, 2);
		length = intUnzip(buf+3, 2);
		colNull = intUnzip(buf+5, 4);
		buf += 9;
		for(int i = 0; i < column_num; ++i){
			single_data.resize(max_length[i]);
			memcpy(&(single_data[0]), buf, max_length[i]);
			data.push_back(single_data);
			buf += max_length[i];
		}
	}
public:
	void insertValue(std::string data){
		origin_data.push_back(data);
		nullList.push_back(false);
	}
	void insertNull(){
		origin_data.push_back("");
		nullList.push_back(true);
	}
	std::string toString(){
		return "0" + intZip(column_num+1,2) + intZip(lenth+RID_LEN,2) + intZip(nullInf, 4) + fillStr(RID, RID_LEN) + data;
	}
	void setLengthAsSysObj(){
		max_length.clear();
		max_length.push_back(RID_LEN);
		max_length.push_back(MAX_TABLE_NAME);
		setData();
	}
	void setLengthAsSysColumn(){
		max_length.clear();
		max_length.push_back(RID_LEN);
		max_length.push_back(MAX_ID);
		max_length.push_back(MAX_COLUMN_NAME);
		max_length.push_back(MAX_COLUMN_TYPE);
		max_length.push_back(MAX_COLUMN_LENGTH);
		max_length.push_back(MAX_COLUMN_RANK);
		max_length.push_back(MAX_COLUMN_NULL);
		setData();
	}
	void setLengthAsSysIndex(){
		max_length.clear();
		max_length.push_back(RID_LEN);
		max_length.push_back(MAX_ID);
		max_length.push_back(MAX_TABLE_INDEX);
		max_length.push_back(MAX_TABLE_KEY);
		max_length.push_back(MAX_TABLE_HAS_INDEX);
		setData();
	}
	void setLength(std::vector<int>& lenList){
		max_length.clear();
		max_length.push_back(RID_LEN);
		for(int i = 0; i < lenList.size(); ++i)
			max_length.push_back(lenList[i]);
		setData();
	}
	void setRID(int id){
		std::stringstream ss;
		ss << id;
		ss >> RID;
	}
	void setRID(std::string id){
		RID = id;
	}
	int getColumnNum(){
		return column_num;
	}
	std::string getColumn(int i){
		if(i > 0)
			return origin_data[i-1];
		else
			return RID;
	}
private:
	void insertColumn(std::string column){
		data += fillStr(column, max_length[cur_column]);
		lenth += max_length[cur_column];
		++ column_num;
		++ cur_column;
	}
	void setData(){
		data.clear();
		lenth = 0;
		column_num = 0;
		cur_column = 1;
		for(int i = 0; i < origin_data.size(); ++i)
			insertColumn(origin_data[i]);
		nullInf = 0;
		for(int i = 0; i < nullList.size(); ++i)
			if(nullList[i])
				nullInf += (unsigned int)(1 << i);
	}
};

#endif // DATA_H
